#include "pressure_keyboard.h"
#include <stdio.h>
#include <stdlib.h>

uint16_t BSP_PressureKeyboard_GetPressureData(volatile Device_PressureKeyboard *dv, int row, int col);

Device_PressureKeyboard BSP_PressureKeyboard_CreateMemory(int nRows, int nCols){
    Device_PressureKeyboard dv;
    
    dv.nCols = nCols;
    dv.nRows = nRows;
    
    dv.rowsGpioPort = (GPIO_TypeDef**)calloc(nRows, sizeof(GPIO_TypeDef*));
    dv.colsGpioPort = (GPIO_TypeDef**)calloc(nCols, sizeof(GPIO_TypeDef*));
    dv.rowsGpioPin = (uint16_t*)calloc(nRows, sizeof(uint16_t));
    dv.colsGpioPin = (uint16_t*)calloc(nCols, sizeof(uint16_t));
    
    dv.pressureKeys = (SubDevice_PressureKey**)calloc(nRows, sizeof(SubDevice_PressureKey*));
    uint8_t i;
    for(i = 0; i < nRows; i++){
        dv.pressureKeys[i] = (SubDevice_PressureKey*)calloc(nCols, sizeof(SubDevice_PressureKey));
    }
    return dv;
}

KeyData BSP_PressureKeyboard_GetCurrentInput(volatile Device_PressureKeyboard *dv){
    KeyData kd;
    uint8_t i, j;
    for(i = 0; i < dv->nRows; i++){
        GPIO_TypeDef *rPort = (dv->rowsGpioPort)[i];
        uint8_t rPin = (dv->rowsGpioPin)[i];
        if(GPIO_ReadInputDataBit(rPort, rPin)){
            for(j = 0; j < dv->nCols; j++){
                GPIO_TypeDef *cPort = (dv->colsGpioPort)[j];
                uint8_t cPin = (dv->colsGpioPin)[j];
                if(GPIO_ReadInputDataBit(cPort, cPin)){
                    kd.valid = 0xff;
                    kd.row = i;
                    kd.col = j;
                    kd.pressureData = BSP_PressureKeyboard_GetPressureData(dv, i, j);
                    return kd;
                }
            }
        }
    }
    kd.valid = 0x00;
    kd.col = 0;
    kd.row = 0;
    kd.pressureData = 0;
    return kd;
}

uint16_t BSP_PressureKeyboard_GetPressureData(volatile Device_PressureKeyboard *dv, int row, int col){
    uint16_t adcData = 0U;
    SubDevice_PressureKey pk =(dv->pressureKeys)[row][col];
    ADC_RegularChannelConfig(pk.adcPort, pk.adcChannel, 1, ADC_SampleTime_480Cycles);
    ADC_SoftwareStartConv(pk.adcPort);
    while(!ADC_GetFlagStatus(pk.adcPort, ADC_FLAG_EOC));
    adcData = ADC_GetConversionValue(pk.adcPort);
    return adcData;
}
